#include <soar.h>

char buf[BUFFER_SIZE];

static int _demo(unsigned int algm, char *key_txt, char *msg,
        unsigned char *enc, unsigned char *plain)
{/*{{{*/
    OSSL_KEY key;
    int res;
    int enc_size;
    int plain_size;

    if((res=ossl_sym_load_key(algm, OSSL_SYM_KEY, key_txt, &key)) == 0)
    {
        printf("key: %s\n", key_txt);
        if((res=ossl_sym_encrypt(key, (unsigned char *)msg, strlen(msg),
                        enc, &enc_size)))
        {
            printf("ossl_sym_encrypt fail, res:%d\n", res);
            return(-1);
        }
        printf("encrypt: %s\n", expand_to_str(enc, enc_size, buf));
        if((res=ossl_sym_decrypt(key, enc, enc_size,
                        plain, &plain_size))) 
        {
            printf("ossl_sym_decrypt fail, res:%d\n", res);
            return(-1);
        }
        printf("decrypt: succeed\n");
        ossl_sym_free_key(key);
    }
    else
    {
        printf("ossl_sym_loadkey fail, res:%d\n", res);
    }

    return(0);
}/*}}}*/

int main(int argc, char *argv[])
{/*{{{*/
    int res;
    char msg[KB(4)];
    unsigned char enc[KB(10)];
    int enc_size;
    unsigned char plain[KB(4)];
    int plain_size;
    OSSL_KEY key;
    char *passwd="Titanic";
    char key_txt[100];
    char iv_txt[100];
    char *key_64 ="C54E6F7DD4DACC1A";
    char *key_128="C54E6F7DD4DACC1AC5B0FA66565A4A60";
    char *key_192="C54E6F7DD4DACC1AC5B0FA66565A4A6036902FDE85880CF4";
    char *key_256="C54E6F7DD4DACC1AC5B0FA66565A4A6036902FDE85880CF4C668AF6B987DB8D0";

    ossl_init();

    strcpy(msg, "落红岂是无情物，化作春泥更护花。");
    printf("plain: %s\n", msg);
    printf("\n");

    printf("********************\n");
    printf("* Load Key(passwd) *\n");
    printf("********************\n");
    if((res=ossl_sym_load_key(OSSL_SYM_DES_CBC, OSSL_SYM_PASSWD,
                    passwd, &key)))
    {
        printf("oss_sym_load_key(PASSWD:%s) fail, res:%d\n",
                passwd, res);
        return(-1);
    }
    ossl_sym_get_key(key, key_txt, iv_txt);
    printf("passwd: %s\nbits: 64\nkey: %s\niv: %s\n",
            passwd, key_txt, iv_txt);
    if((res=ossl_sym_encrypt(key, (unsigned char *)msg, strlen(msg),
                    enc, &enc_size)))
    {
        printf("ossl_sym_encrypt fail, res:%d\n", res);
        return(-1);
    }
    printf("encrypt: %s\n", expand_to_str(enc, enc_size, buf));
    if((res=ossl_sym_decrypt(key, enc, enc_size,
                    plain, &plain_size))) 
    {
        printf("ossl_sym_decrypt fail, res:%d\n", res);
        return(-1);
    }
    printf("decrypt: succeed\n");
    ossl_sym_free_key(key);
    printf("\n");

    printf("***********\n");
    printf("* DES_CBC *\n");
    printf("***********\n");
    if(_demo(OSSL_SYM_DES_CBC, key_64, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***********\n");
    printf("* DES_ECB *\n");
    printf("***********\n");
    if(_demo(OSSL_SYM_DES_ECB, key_64, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* DES_EDE_CBC *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_DES_EDE_CBC, key_128, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* DES_EDE_ECB *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_DES_EDE_ECB, key_128, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("****************\n");
    printf("* DES_EDE3_CBC *\n");
    printf("****************\n");
    if(_demo(OSSL_SYM_DES_EDE3_CBC, key_192, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("****************\n");
    printf("* DES_EDE3_ECB *\n");
    printf("****************\n");
    if(_demo(OSSL_SYM_DES_EDE3_ECB, key_192, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* AES_128_CBC *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_AES_128_CBC, key_128, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* AES_128_ECB *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_AES_128_ECB, key_128, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* AES_192_CBC *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_AES_192_CBC, key_192, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* AES_192_ECB *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_AES_192_ECB, key_192, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* AES_256_CBC *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_AES_256_CBC, key_256, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("***************\n");
    printf("* AES_256_ECB *\n");
    printf("***************\n");
    if(_demo(OSSL_SYM_AES_256_ECB, key_256, msg, enc, plain))
        return(-1);
    printf("\n");

    printf("********************************\n");
    printf("* AES_128_CBC + random_padding *\n");
    printf("********************************\n");
    char str[30]="hello world!";
    int str_size=strlen(str);
    printf("src(%d): %s\n", str_size, str);
    random_padding((unsigned char *)str, str_size,
            (unsigned char *)str, &str_size);
    printf("padding(%d): %s\n", str_size, str);
    if(_demo(OSSL_SYM_AES_128_CBC, key_128, str, enc, plain))
        return(-1);
    random_unpadding((unsigned char *)str, str_size,
            (unsigned char *)str, &str_size);
    printf("unpadding(%d): %s\n", str_size, str);
    printf("\n");

    ossl_clean();

    return(0);
}/*}}}*/
